#ifndef __FLOAT__
#define __FLOAT__

#include <sstream>
#include <iostream>
#include <string>
#include <cassert>
#include <bitset>
#define MAX_PRECISION 50
#define COTA_POR_PERIODICO MAX_PRECISION
#define nat unsigned short
#define unsh(a) (((nat)a)&0xff)
typedef char byte;

using namespace std;

class Float{
	
	public:

		/**
		 * Constructores
		 */
		Float();
		Float(const string&);
		Float(const float&);
		Float(const Float&);
		~Float();
		Float& operator=(const Float&);

		/**cout
		 * operadores de comparacion
		 */
		bool operator== (const Float&) const;
		bool operator!=(const Float&) const;
		bool operator<(const Float&) const;
		bool operator<=(const Float&) const;
		bool operator>(const Float&) const;
		bool operator>=(const Float&) const;
		
		/**
		 * operadores aritmeticos
		 */
		Float operator+(const Float&) const;
		Float operator-(const Float&) const;
		Float operator*(const Float&) const;
		Float operator>>(const unsigned int&);


		/**
		 * operadores de asignacion y aritmeticos
		 */
		void operator+=(const Float&);
		void operator-=(const Float&);
		void operator*=(const Float&);
		void operator>>=(unsigned int);
		
		string mostrar() const;
	
		char* dameMantisa() const;
		int damePre() const;
		int dameExp() const;
		bool dameSig() const;

	private:
		void signoYSeparar(const string&,string&,string&);
		void dividirPorDos(byte*, int, int);
		bool multPorDos(byte*, int);
		void reverse(string&);
		void entChar2bin(string&);
		void fracChar2bin(string&);
		void calcularPotencia(string&, string&);
		
		// mantisa[0] es la parte mas significativa (big-indian)
		char* mantisa;
		int precision;
		int exponente;
		bool signo;

};

bool noCero(string& numero);
void agregarCerosIzq(string& num);
void agregarCerosDer(string& num);
ostream& operator<<(ostream& out, const Float& f) {
	out << f.mostrar();
	return out;
}

/** contructor por defecto 
    inicializa el float en estado invalido.
    */
Float::Float(){
	precision = 0;
	mantisa = NULL;
	exponente = 0;
	signo = false;	
}

/** constructor que recibe como parametro un string con el float en base 10*/
Float::Float(const string &num) {
	string ent = "";
	string frac = "";
	//calcula exponente y singno y borra los ceros redundantes
	signoYSeparar(num, ent, frac);
	bool hayEntero = (ent.size() != 0 && noCero(ent));
	bool hayFraccion = (frac.size() != 0 && noCero(frac));
	//converitr num a binario
	// lo deja en el siguiente formato.
	// string[0] es el mas significativo.
	if(hayEntero)
		entChar2bin(ent);
	if(hayFraccion)
		fracChar2bin(frac);

	
	calcularPotencia(ent,frac);
	string numB2 = ent + frac;
	int rest = (numB2.size()%8 == 0)?0:1;
	precision = numB2.size()/8 + rest;
	mantisa = new byte[precision];
	
	byte valor;
	int size = numB2.size();
	for(int x = 0; x < precision*8; x+=8){
		valor = 0;
		int pos;
		for(pos = 0; pos < 8 && (pos+x) < size; pos++){
			valor=valor<<1;
			valor += (numB2[x+pos] - '0');
		}
		if(x+pos > size){
			valor<<=(8-pos);
		}
		mantisa[x/8] = valor;
	}
    int correrPrecision = 0;
    for( int x = this->precision-1; x>=0 && this->mantisa[x] == 0; x--){
        correrPrecision++;
    }
    this->precision -= correrPrecision;
    if(precision!=0){
        int restarExponente = 0;
        for(int x = 0; this->mantisa[x] == 0; x++){
            restarExponente++;
        }
        this->precision -= restarExponente;
        this->exponente -= restarExponente;
        byte* temp = this->mantisa;
        this->mantisa = new byte[this->precision];
        for(int pos = 0; pos < this->precision; pos++){
            this->mantisa[pos] = temp[restarExponente + pos];
        }
        delete []temp;
    }
    if(this->precision == 0){
        this->signo = false;
        this->exponente = 0;
		this->mantisa = NULL;
    }
}

/** constructor que recibe un float de la maquina y lo hace de tupo Float */
Float::Float(const float& f){
	std::stringstream ss;
	ss <<fixed <<  f;
	string s = ss.str();
    //MAL ARREGLAR
	this->mantisa = NULL;
	this->precision = 0;
	this->exponente = 0;
	this->signo = false;
	//TODO this(s);
	Float pep(s);
	*this = pep;
}

/** constructor por copia*/
Float::Float(const Float& f){
	this->signo = f.signo;
	this->precision = f.precision;
	this->exponente = f.exponente;
    if( this->precision != 0 && f.mantisa != NULL){
        	this->mantisa = new byte[f.precision];
        	for(int x = 0; x < this->precision; x++){
            		this->mantisa[x] = f.mantisa[x];
        	}
	} else {
		this->mantisa = NULL;
	}
}

Float::~Float(){
	if(this->mantisa != NULL){
		delete [] mantisa;
        mantisa = NULL;
	}
}

Float& Float::operator=(const Float& other){
	if(this!= &other){
		if(this->mantisa != NULL){
			delete [] mantisa;
		}
		//TODO usar constructor por copia
		this->signo = other.signo;
		this->precision = other.precision;
		this->exponente = other.exponente;
        if(this->precision!=0 && other.mantisa!=NULL){
            this->mantisa = new byte[this->precision];
            for(int x = 0; x < this->precision; x++){
                this->mantisa[x] = other.mantisa[x];
            }
        }
	}
	return *this;

}

/**************************************
* operadores de comparacion
**************************************/
bool Float::operator== (const Float& other) const {
//		char* mantisa;
//		long long int precision;
//		long long int exponente;
//		bool signo;
	if(this->precision == 0 && other.precision == 0
        || this->mantisa == NULL && other.mantisa == NULL){
		return true;
	}
	if (	this->signo != other.signo 
		|| 	this->exponente != other.exponente
		|| 	this->precision != other.precision) {
		return false;
	}
	bool ret = true;
	for(int x = 0; x < this->precision; x++){
		ret = ret && (this->mantisa[x] == other.mantisa[x]);
	}
	return ret;
}

bool Float::operator!=(const Float& f) const {
	return !(*this == f);
}

bool Float::operator<(const Float& other) const {
	bool ret;
	if((*this == Float("0.0")) &&	(other == Float("0.0"))){
		return false;
	}
	if(this->signo == other.signo){
		if(this->exponente == other.exponente){
			// exponentes iguales
			int minimo = (this->precision<other.precision)?this->precision:other.precision;
			bool termino = false;
			bool igual = true;
			for(int x = 0; x < minimo && !termino; x++){
				if(unsh(this->mantisa[x]) < unsh(other.mantisa[x])){
					ret = true;
					termino = true;
					igual = false;
				} else if(unsh(this->mantisa[x]) > unsh(other.mantisa[x])){
					ret = false;
					igual = false;
					termino = true;
				}
			}
			//en caso que sean iguales en todos los numeros en comun
			if(igual){
				ret = (this->precision < other.precision);
			}
			if(this->signo && !igual){
				ret = !ret;
			}
		} else {
		ret =  (this->signo && this->exponente > other.exponente);
		ret = ret || ((!this->signo) && this->exponente < other.exponente);
		}
		// los signos son iguales
	} else {
		ret = this->signo;	
	}
	return ret;
}

bool Float::operator<=(const Float& f) const {
	return  (*this < f) ||(*this == f);
}

bool Float::operator>(const Float& f) const {
	return !(*this <= f);
}

bool Float::operator>=(const Float& f) const {
	return !(*this < f);
}

/**********************************
		 * operadores aritmeticos
**********************************/
Float Float::operator+(const Float& other) const {
	Float f(*this); 
	f+=other;
	return f;
}

Float Float::operator-(const Float& other) const{
	// a - b = -(-a + b)
	Float f(*this);
	f.signo = !f.signo;
	f+=other;
	f.signo = !f.signo;
	return f;
	
}

Float Float::operator*(const Float& other) const{
	Float f(*this);
	f*=other;
	return f;
}

Float Float::operator>>(const unsigned int& n) {
	Float f(*this);
	f>>=n;
	return f;
}

/****************************************
 * operadores de asignacion y aritmeticos
*****************************************/
void Float::operator+=(const Float& f){
    if(f == Float("0.0")){
        return;
    }
	if(*this == Float("0.0")){
        *this = f;
        return;
    }
    if(*this == f){
    	Float dos("2");
    	(*this) *= dos;
    	return;
    }
    this->signo = !this->signo;
    if( *this == f ){
        *this = Float("0.0");
        return;
    }
    this->signo = !this->signo;
    
    
    
	if(this->signo == f.signo){
		int inicio;
		bool carry;
		byte * result;
		// separo aguas
		// hago la cuenta principal en funcion del exponente
		if(this->exponente < f.exponente){
            // salvo la precision de este.
			int thisPreci = this->precision;
			// calulo la precision.
			if(this->precision + (f.exponente - this->exponente) < f.precision){
				this->precision = f.precision;
			} else { 
				this->precision += (f.exponente - this->exponente);
			}
            if(this->precision >= MAX_PRECISION)
                this->precision = MAX_PRECISION - 1;
			// relleno el arreglo final
			result = new byte[this->precision];
			assert(this->precision >= f.precision);
			for(int x = 0; x < f.precision; x++)
				result[x] = f.mantisa[x];
				
			for(int x = f.precision; x < this->precision; x++)	
				result[x] = 0;
				
			// averiguo donde empieza el numero mas chico en el arreglo final.
			int inicio = f.exponente - this->exponente;
            if(inicio >= MAX_PRECISION)
                inicio = MAX_PRECISION - 1;
			assert(inicio <= this->precision);
			carry = false;
			//obtener el it del mas chico (es necesario el if, por los %MAXPRECI)
			int itChico;
			if(this->precision - inicio > thisPreci){
				itChico = thisPreci-1;
			} else {
				itChico = this->precision - inicio - 1;
			}
			//hago las cuentas
			for(int x = itChico; x>=0; x--){
				byte pre = result[inicio + x];
				result[inicio + x] += ((byte)(carry)?1:0);
				carry = unsh(pre) > unsh(result[inicio+x]);
				pre = result[inicio+x];
				result[inicio + x] += this->mantisa[x];
				carry = carry || unsh(pre) > unsh(result[inicio+x]);
                
			}
			// termino de pasar carries.
			int x = inicio - 1;
			while(carry && x >= 0){
				byte pre = result[x];
				result[x] += ((byte)(carry)?1:0);
				carry = unsh(pre) > unsh(result[x]);
                x--;
			}
			//actualizo exponente
			this->exponente = f.exponente;
		} else { //this->exponente >= f.exponente
			// salvo la precision de este.
			int thisPreci = this->precision;
			// calulo la precision.
			if(f.precision + this->exponente - f.exponente > this->precision){
				this->precision = f.precision;
				this->precision += (this->exponente - f.exponente);
			}

           
           if(this->precision >= MAX_PRECISION)
               this->precision = MAX_PRECISION - 1;
			// relleno el arreglo final
			result 	= new byte[this->precision];
			assert(this->precision >= thisPreci);
			for(int x = 0; x < thisPreci; x++)
				result[x] = this->mantisa[x];
				
			for(int x = thisPreci; x < this->precision; x++)	
				result[x] = 0;
				
			// averiguo donde empieza el numero mas chico en el arreglo final.
			int inicio = this->exponente - f.exponente;
            if(inicio >= MAX_PRECISION)
                inicio = MAX_PRECISION - 1;
			carry = false;
			//obtener el it del mas chico (es necesario el if, por los %MAXPRECI)
			int itChico;
			if(this->precision - inicio > f.precision){
				itChico = f.precision-1;
			} else {
				itChico = this->precision - inicio - 1;
			}
			//hago las cuentas
			for(int x = itChico; x>=0; x--){
				byte pre = result[inicio + x];
				result[inicio + x] += ((byte)(carry)?1:0);
				carry = unsh(pre) > unsh(result[inicio+x]);
				pre = result[inicio+x];
				result[inicio + x] += f.mantisa[x];
				carry = carry || unsh(pre) > unsh(result[inicio+x]);
			}
			//termino de pasar carries
			int x = inicio - 1;
			while(carry && x >= 0){
				byte pre = result[x];
				result[x] += ((byte)(carry)?1:0);
				carry = unsh(pre) > unsh(result[x]);
                x--;
			}
		}
		// a partir de aqui independiente de los floats paramatros
		//en caso de q se haya carry al finalizar
        
        if(this->mantisa != NULL){
            delete[]this->mantisa;
            this->mantisa = NULL;
        }
		if(carry && (this->precision-1) < MAX_PRECISION){
			this->mantisa = new byte[this->precision+1];
			this->mantisa[0] = 1;
            for(int x = 0; +x < this->precision; x++)
				this->mantisa[x+1] = result[x];
			this->precision++;
            this->exponente++;
		} else if(carry && !(this->precision < MAX_PRECISION)) {
			this->mantisa = new byte[this->precision];
            this->mantisa[0] = 1;
			for(int x = 1; x < this->precision;x++)
				this->mantisa[x] = result[x-1];
            this->exponente++;
		} else {
			this->mantisa = result;
			result = NULL;
		}
		if(result!= NULL){
			delete[]result;
            result = NULL;
        }
		//por como se hace la suma no deberia haber ceros al principio.
		assert(this->mantisa[0]!=0);
		// normalizo (quitar ceros del final);
		int pos = this->precision-1;
		int ceros = 0;
		while(pos >= 0 && mantisa[pos] == 0){
			ceros++;
            pos--;
		}
		if(ceros > 0){
			byte * temp;
			this->precision -= ceros;
			temp = this->mantisa;
			this->mantisa = new byte[this->precision];
			for(int x = 0; x < this->precision ; x++ )
				this->mantisa[x] = temp[x];
            delete[]temp;
		}
	} else {// distinto signo.
        bool borrow;
        byte* result;
		Float aux(f);
		bool elSigno = this->signo;
		this->signo = false;
		aux.signo = false;
		//me guardo el signo de this y les calculo el modulo (sacarle el signo)
		//una vez hecho eso comparo y separo entre el mas grande y el mas chico.
		if(*this > aux){
            // |this| > |f|
            // this en modulo es mayor a f en modulo.
            // salvo la precision de este.
            int thisPreci = this->precision;
            // calulo la precision.
            if(f.precision + this->exponente - f.exponente >= this->precision){
                this->precision = f.precision;
                this->precision += (this->exponente - f.exponente);
            }
            
            if(this->precision >= MAX_PRECISION)
                this->precision = MAX_PRECISION - 1;
            
            // relleno el arreglo final
            result  = new byte[this->precision];
            for(int x = 0; x < thisPreci; x++)
                result[x] = this->mantisa[x];
            
            for(int x = thisPreci; x < this->precision; x++)    
                result[x] = 0;
            
            // averiguo donde empieza el numero mas chico en el arreglo final.
            int inicio = this->exponente - f.exponente;
            if(inicio >= MAX_PRECISION)
                inicio = MAX_PRECISION - 1;
            assert(inicio <= this->precision);
            borrow = false;
            //obtener el it del mas chico (es necesario el if, por los %MAXPRECI)
            int itChico;
            if(this->precision - inicio > f.precision){
                itChico = f.precision-1;
            } else {
                itChico = this->precision - inicio - 1;
            }
            //hago las cuentas
            for(int x = itChico; x>=0; x--){
                byte pre = result[inicio + x];
                result[inicio + x] -= ((byte)(borrow)?1:0);
                borrow = unsh(pre) < unsh(result[inicio+x]);
                pre = result[inicio+x];
                result[inicio + x] -= f.mantisa[x];
                borrow = borrow || unsh(pre) < unsh(result[inicio+x]);
            }
            //termino de sacar borrows
            int x = inicio - 1;
            while(borrow && x >= 0){
                byte pre = result[x];
                result[x] -= ((byte)(borrow)?1:0);
                borrow = unsh(pre) < unsh(result[x]);
                x--;
            }
            this->signo = elSigno;
		} else {
            // |this| <= |f|
            // this en modulo es menor a f en modulo.
            // salvo la precision de este.
            int thisPreci = this->precision;
            // calulo la precision.
            if(this->precision + f.exponente - this->exponente > f.precision){
                this->precision += (f.exponente - this->exponente);
            } else {
                this->precision = f.precision;
            }
            
            if(this->precision >= MAX_PRECISION)
                this->precision = MAX_PRECISION - 1;
            // relleno el arreglo final
            result  = new byte[this->precision];
            for(int x = 0; x < f.precision; x++)
                result[x] = f.mantisa[x];
            
            for(int x = f.precision; x < this->precision; x++)    
                result[x] = 0;
            
            // averiguo donde empieza el numero mas chico en el arreglo final.
            int inicio = f.exponente - this->exponente;
            if(inicio >= MAX_PRECISION)
                inicio = MAX_PRECISION - 1;
            assert(inicio <= this->precision);
            borrow = false;
            //obtener el it del mas chico (es necesario el if, por los %MAXPRECI)
            int itChico;
            if(this->precision - inicio > thisPreci){
                itChico = thisPreci-1;
            } else {
                itChico = this->precision - inicio - 1;
            }
            //hago las cuentas
            for(int x = itChico; x>=0; x--){
                byte pre = result[inicio + x];
                result[inicio + x] -= ((byte)(borrow)?1:0);
                borrow = unsh(pre) < unsh(result[inicio+x]);
                pre = result[inicio+x];
                result[inicio + x] -= this->mantisa[x];
                borrow = borrow || unsh(pre) < unsh(result[inicio+x]);
            }
            //termino de sacar borrows
            int x = inicio - 1;
            while(borrow && x >= 0){
                byte pre = result[x];
                result[x] -= ((byte)(borrow)?1:0);
                borrow = unsh(pre) < unsh(result[x]);
                x--;
            }
            this->signo = !elSigno;
            this->exponente = f.exponente;
		}
        assert(!borrow);
        if(this->mantisa != NULL){
            delete [] this->mantisa;
            this->mantisa = NULL;
        }
        this->mantisa = new byte[this->precision];
        for(int x = 0; x < this->precision; x++)
            this->mantisa[x] = result[x];
        //normalizacion
        int correrPrecision = 0;
        for( int x = this->precision-1; x>=0 && this->mantisa[x] == 0; x--){
            correrPrecision++;
        }
        this->precision -= correrPrecision;
        if(precision!=0){
            int restarExponente = 0;
            for(int x = 0; this->mantisa[x] == 0; x++){
                restarExponente++;
            }
            this->precision -= restarExponente;
            this->exponente -= restarExponente;
            byte* temp = this->mantisa;
            this->mantisa = new byte[this->precision];
            for(int pos = 0; pos < this->precision; pos++){
                this->mantisa[pos] = temp[restarExponente + pos];
            }
            delete []temp;
        }
        if(this->precision == 0){
            this->signo = false;
            this->exponente = 0;
            if(this->mantisa != NULL){
                delete [] this->mantisa;
                this->mantisa = NULL;
            }
        }
		
	}

}
void Float::operator*=(const Float& f){
    if( *this == Float("0.0") || f == Float("0.0")){
        this->precision = 0;
        this->exponente = 0;
        this->signo = false;
        if(this->mantisa != NULL){
            delete[] this->mantisa;
            this->mantisa = NULL;
        }
        this->mantisa = NULL;
        return;
    }
	this->signo = (this->signo != f.signo);
	this->exponente += f.exponente;
	byte* num1;
	nat* result;
	const byte* num2;
	int size;
	if(this->precision < f.precision) {
		size = f.precision;
		num2 = f.mantisa;
		num1 = new byte[size];
		for(int i=0; i < this->precision; i++)
			num1[i] = this->mantisa[i];
		for(int i = this->precision; i < size; i++)
			num1[i] = 0;
	} else {
		size = this->precision;
		num2 = this->mantisa;
		num1 = new byte[size];
		for(int i = 0; i < f.precision; i++)
			num1[i] = f.mantisa[i];
		for(int i = f.precision; i < size; i++)
			num1[i] = 0;
	}
	this->precision = 2*size;
	result = new nat[this->precision];
	for(int x = 0; x < this->precision; x++)
		result[x] =0;
	nat carry;
	for(int x = 0; x <size; x++){
		carry = 0;
		nat value1 = unsh(num1[size - 1 - x]);
		int pos = x;
		for(int y = 0; y < size; y++){
			nat value2 = unsh(num2[size - 1 - y]);
			result[pos] += carry;
			carry = (result[pos]>>8)&0xff;
			result[pos] &= 0xff;
			result[pos] += value2*value1;
            carry += (result[pos]>>8)&0xff;
			result[pos] &= 0xff;
			pos++;
		}
		while(carry!=0){
			result[pos]+=carry;
            carry = (result[pos]>>8)&0xff;
			result[pos] &= 0xff;
			pos++;			
		}
        assert(pos<=(size*2));
	}
	delete[] num1;
    if(this->mantisa != NULL){
        delete[] this->mantisa;
        this->mantisa = NULL;
    }
	this->mantisa = new byte[this->precision];
	for(int x = 0; x < this->precision; x++){
		if(result[x]>255){
			assert(false);
		}
		this->mantisa[this->precision -1 - x] = result[x];
	}
	delete[] result;
	int correrPrecision = 0;
	for( int x = this->precision-1; x>=0 && this->mantisa[x] == 0; x--){
		correrPrecision++;
	}
	this->precision -= correrPrecision;
	if(precision!=0){
		int restarExponente = 0;
		for(int x = 0; this->mantisa[x] == 0; x++){
			restarExponente++;
		}
		this->precision -= restarExponente;
		this->exponente -= restarExponente;
		byte* temp = this->mantisa;
		this->mantisa = new byte[this->precision];
		for(int pos = 0; pos < this->precision; pos++){
			this->mantisa[pos] = temp[restarExponente + pos];
		}
		delete []temp;
	} 
	if(this->precision == 0){
		this->signo = false;
		this->exponente = 0;
		if(this->mantisa != NULL){
			delete [] this->mantisa;
			this->mantisa = NULL;
		}
	}
}

void Float::operator>>=(unsigned int n){
	int restaExponente = n/8;
	int shift = n%8;
	if(*this == Float("0.0")){return;}
	this->exponente -= restaExponente;
	if(shift != 0){
		if(this->precision+1 < MAX_PRECISION){
			this->precision++;
		}
		byte* temp = new byte[this->precision];
		temp[0]=0;
		for(int x = 0; x < this->precision-1; x++){
			temp[x]	+= this->mantisa[x]>>shift;
			temp[x+1] = this->mantisa[x]<<(8-shift);
		}
		delete [] this->mantisa;
		this->mantisa = temp;
	}
    int correrPrecision = 0;
    for( int x = this->precision-1; x>=0 && this->mantisa[x] == 0; x--){
        correrPrecision++;
    }
    this->precision -= correrPrecision;
    if(precision!=0){
        int restarExponente = 0;
        for(int x = 0; this->mantisa[x] == 0; x++){
            restarExponente++;
        }
        this->precision -= restarExponente;
        this->exponente -= restarExponente;
        byte* temp = this->mantisa;
        this->mantisa = new byte[this->precision];
        for(int pos = 0; pos < this->precision; pos++){
            this->mantisa[pos] = temp[restarExponente + pos];
        }
        delete []temp;
    } 
    if(this->precision == 0){
        this->signo = false;
        this->exponente = 0;
        if(this->mantisa != NULL){
			delete [] this->mantisa;
			this->mantisa = NULL;
		}
    }
}

/******************************************************
***************** PRIVADAS ****************************/

void Float::calcularPotencia(string &ent, string &frac){
	exponente = 0;
	if(ent.size() > 0 && noCero(ent) ){
		int rest = (ent.size()%8!=0)?1:0;
		this->exponente = ent.size()/8 + rest;
	} else {
		for(; frac[exponente] == '0'; exponente++){}
		exponente /= 8;
		if(exponente > 0)
			frac.erase(0,(exponente*8-1));
		exponente = -exponente;
	}
} 
	

void Float::signoYSeparar(const string& num, string &entero, string &fraccion) {
	int x = 0;
	signo = false;
	if(num[x] == '-') {
		x++;
		signo = true;
	}
	// elimino los 0s del principio
	while( num[x] == '0'){
		x++;
	}
	bool cambio = false;
	// si tiene parte entera, la voy acumulando en s(que luego sera ent)
	while( x < num.size() ){
		if( num[x] == ',' || num[x] == '.' ){
			cambio = true;
			x++;
		}
		if(cambio && (x < num.size()))
			fraccion += num[x];
		else
			entero += num[x];
		x++;
	}
	
	// una vez que llegue al final empiezo a eliminar los 0s del final
	x = fraccion.size();
	while(x > 0 && fraccion[x-1] == '0')
		x--;
	fraccion.erase(x);
}

//reverso de string in place.
void Float::reverse(string &numB2) {
	int tam=numB2.size();
	for(int i=0;i<tam/2;i++) {
		char tmp = numB2[i];
		numB2[i] = numB2[tam-1-i];
		numB2[tam-1-i] = tmp;
	}		
}

// recibe un arreglo de char representando numeros, tal que array[0] 
// es la parte menos significativa
void Float::dividirPorDos(byte* arr, int inicio, int tamanio) {
	while(inicio < tamanio) {
		byte carry = (arr[inicio]%2) * 10;
		arr[inicio] >>= 1;
		inicio++;
		if(inicio < tamanio)
			arr[inicio] += carry;
	}
}

void Float::entChar2bin(string& numero){
	int tamanio = numero.size();
	byte valor;
	
	// tranformamos de string de numeros decimales en char a 
	// array de numeros decimales en valor(array[0] es 
	// la posicion menos signficativa)
	byte numArr[tamanio];
	for(int i=0; i<tamanio; i++) {
		valor = (byte)numero[i]-'0';
		if(!(0 <= valor && valor <=9)){
			cout << ""+numero[i] << endl;
			assert(false);
		}
		numArr[i] = valor;
	}
	//dejamos el numero en el string de forma binaria
	// tal que string[0] es el menos significativo
	int newTam = 0;
	string numB2 = "";
	while(newTam < tamanio || numArr[tamanio - 1] != 0) {
		if(numArr[tamanio - 1]%2 == 0) {
			numB2 +=  "0";
		} else {
			numB2 += "1";
		}
		dividirPorDos(numArr, newTam, tamanio);
		if(numArr[newTam] == 0)
			newTam++;
	}
	numero = numB2;
	// despues del reverse el string[0] es el mas significativo
	reverse(numero);
	agregarCerosIzq(numero);
}

bool Float::multPorDos(byte* arr, int inicio) {
	int carry = 0;
	while(inicio >= 0) {
		arr[inicio] += arr[inicio];
		arr[inicio] += carry;
		// multiplicar un numero por 2 y sumarle uno tiene a los sumo carry == 1
		if(arr[inicio] > 9) {
			carry = 1;
			arr[inicio] -= 10;
		} else {
			carry = 0;
		}
		inicio--;
		
	}
	return carry==0;
}

// recibe la parte fraccionaria y la deja lista para ser parseada.
void Float::fracChar2bin(string& numero) {
	int tamanio = numero.size();
	byte valor;
	byte numArr[tamanio];
	// string => array(char) talque array[0] es la parte mas signficativa
	for(int i=0; i<tamanio; i++) {
		valor = (byte)numero[i]-'0';
		if(!(0 <= valor && valor <=9)){
			cout << ""+numero[i] << endl;
			assert(false);
		}
		numArr[i] = valor;
	}
	// numarr[0] es el mas significativo
	// hacemos la fraccion, tenemos en cuenta los numeros 
	// periodicos acotandolos por COTAPORPERIODICO
	int newTam = tamanio - 1;
	string numB2 = "";
	int veces = 0;
	while( newTam >= 0  && (veces < COTA_POR_PERIODICO)) {
		
		bool esCero = multPorDos(numArr, newTam);
		if(esCero) {
			numB2 +=  "0";
		} else {
			numB2 +=  "1";
		}
		while(newTam>=0 && numArr[newTam] == 0)
			newTam--;
		veces ++;
	}
	numero = numB2;
	agregarCerosDer(numero);
}


/***********************************************************
************* STREAMS ************************************/


string Float::mostrar() const{
	string result = "";
	if(signo){
		result = "-";
	}
	result += "0,";
	char buffer[2];
	for(int x = 0; x < this->precision; x++) {
		stringstream ss;
		ss <<  unsh(mantisa[x]);
		result += ss.str();
		if(x < this->precision-1)
			result += ".";
	}
	result += "×e^";
	stringstream ss;
	ss << exponente;
	result += ss.str();
	return result;
}
/***********************************
**********  AUXILIARES ***************/
bool noCero(string& numero){
	bool ret = false;
	int largo = numero.size();
	for(int x = 0; x < largo; x++){
		ret = ret || (numero[x] != '0');
	}
	return ret;
}
void agregarCerosIzq(string& num){
	int cant = (-(num.size()%8))%8;
	for(; cant > 0; cant--)
		num = "0"+num;
}
void agregarCerosDer(string& num){
	int cant = (-(num.size()%8))%8;
	for(; cant > 0; cant--)
		num = num+"0";
}
	
#endif


